﻿using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using MyCompany.MyProject.Common;
using MyCompany.MyProject.Common.Extensions;
using MyCompany.MyProject.Common.LogHelper;
using Newtonsoft.Json;
using System.Text.RegularExpressions;

#nullable disable

namespace MyCompany.MyProject.Extensions.Middlewares;

public class RequestResponseLogMiddleware
{
    private readonly RequestDelegate requestDelegate;
    private readonly ILogger<RequestResponseLogMiddleware> logger;

    public RequestResponseLogMiddleware(RequestDelegate requestDelegate, ILogger<RequestResponseLogMiddleware> logger)
    {
        this.requestDelegate = requestDelegate;
        this.logger = logger;
    }

    /// <summary>
    /// 执行中间件
    /// </summary>
    /// <param name="context"></param>
    /// <returns></returns>
    public async Task InvokeAsync(HttpContext context)
    {
        if (AppSettings.app("Middleware", "RequestResponseLog", "Enabled").ObjToBool())
        {
            // 过滤 只有接口
            if (context.Request.Path.Value.Contains("api"))
            {
                context.Request.EnableBuffering();

                // 记录请求数据
                await RequestDataLog(context);

                await requestDelegate(context);

                // 记录响应数据
                ResponseDataLog(context.Response);
            }
            else
            {
                await requestDelegate(context);
            }
        }
        else
        {
            await requestDelegate(context);
        }
    }

    /// <summary>
    /// 记录请求日志内容
    /// </summary>
    /// <param name="context"></param>
    /// <returns></returns>
    private async Task RequestDataLog(HttpContext context)
    {
        var request = context.Request;
        var sr = new StreamReader(request.Body);
        RequestLogInfo requestLogInfo = new RequestLogInfo()
        {
            Path = request.Path,
            QueryString = request.QueryString.ToString(),
            BodyData = await sr.ReadToEndAsync()
        };
        var content = JsonConvert.SerializeObject(requestLogInfo);
        if (!string.IsNullOrEmpty(content))
        {
            Parallel.For(0, 1, e =>
            {
                LogLock.OutLogAOP("RequestResponseLog", context.TraceIdentifier, new string[] { "Request Data - RequestDataType:" + requestLogInfo.GetType().ToString(), content });
            });
            request.Body.Position = 0;
        }

    }

    /// <summary>
    /// 记录响应日志内容
    /// </summary>
    /// <param name="context"></param>
    /// <returns></returns>
    private void ResponseDataLog(HttpResponse response)
    {
        var responseBody = response.GetResponseBody();
        // 出去 HTML
        var reg = "<[^>]+>";
        if (!string.IsNullOrEmpty(responseBody))
        {
            var isHtml = Regex.IsMatch(responseBody, reg);
            Parallel.For(0, 1, e =>
            {
                LogLock.OutLogAOP("RequestResponseLog", response.HttpContext.TraceIdentifier,
                    new string[] { "Response Data -  ResponseJsonDataType:" + responseBody.GetType().ToString(), responseBody });
            });
        }
    }

}
